#include "bsp_can.h"
#include "systick.h"

uint8_t can_frame_count = 0;

can_receive_message_struct receive_message;
can_trasnmit_message_struct transmit_message;

static void can_gpio_init(void)
{
	/* enable CAN clock */
	rcu_periph_clock_enable(RCU_CAN0);
	
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_AF);

	gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
	gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);

}

static void can_networking_init()
{
	can_parameter_struct            can_parameter;
	can_filter_parameter_struct     can_filter;

	can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
	can_struct_para_init(CAN_FILTER_STRUCT, &can_filter);

	/* initialize CAN register */
	can_deinit(CAN0);

	/* initialize CAN */
	can_parameter.time_triggered = DISABLE;
	can_parameter.auto_bus_off_recovery = ENABLE;
	can_parameter.auto_wake_up = ENABLE;
	can_parameter.no_auto_retrans = DISABLE;
	can_parameter.rec_fifo_overwrite = DISABLE;
	can_parameter.trans_fifo_order = DISABLE;
	can_parameter.working_mode = CAN_NORMAL_MODE;
	/* bound setting */
	can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
	can_parameter.time_segment_1 = CAN_BT_BS1_5TQ;
	can_parameter.time_segment_2 = CAN_BT_BS2_6TQ;
	
	can_parameter.prescaler = 12;
	can_init(CAN0, &can_parameter);

	/* CAN0 filter number */
	can_filter.filter_number = 0;
	/* initialize filter */    
	can_filter.filter_mode = CAN_FILTERMODE_MASK;
	can_filter.filter_bits = CAN_FILTERBITS_32BIT;
	can_filter.filter_list_high = 0x0000;
	can_filter.filter_list_low = 0x0000;
	can_filter.filter_mask_high = 0x0000;
	can_filter.filter_mask_low = 0x0000;  
	can_filter.filter_fifo_number = CAN_FIFO0;
	can_filter.filter_enable = ENABLE;
	can_filter_init(&can_filter);
}

void bsp_can_init()
{
	can_gpio_init();
	nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn, 3, 0);
	can_networking_init();
    can_interrupt_enable(CAN0, CAN_INT_RFNE0);
}

/* CAN send msg */
uint8_t can_send_msg(uint32_t id, uint8_t *msg, uint8_t len)
{
	uint8_t i = 0;
	can_trasnmit_message_struct tx_message;
	
	// tx_message.tx_sfid = id;
	// tx_message.tx_ff = CAN_FF_STANDARD;  /* 标准帧ID: 8bit */

	tx_message.tx_efid = id;
	tx_message.tx_ff = CAN_FF_EXTENDED;	/* 扩展帧ID: 29bit */

	tx_message.tx_ft = CAN_FT_DATA;  /* 数据帧 */
	tx_message.tx_dlen = len;
	for (i = 0; i < len; i++)
		tx_message.tx_data[i] = msg[i];
	can_message_transmit(CAN0, &tx_message);
	delay_1ms(1);
	return 0;
}

/* fifo is_empty? */
uint8_t is_empty(fifo_t* fifo)
{
	return (fifo->head == fifo->tail);
}

/* fifo is full? */
uint8_t is_full(fifo_t* fifo)
{
	return ((fifo->tail + 1)%(fifo->size) == fifo->head);
}

/* 入队, 向FIFO写入len字节数据 */
void copy_to_fifo(fifo_t* fifo, const uint8_t *from, uint8_t len)
{
	uint8_t i = 0;
	while (!(is_full(fifo)) && i < len) {
		fifo->tail = (fifo->tail + 1)%(fifo->size);
		fifo->rxbuffer[fifo->tail] = from[i++];
	}
}

/* 出队, 从FIFO中读取len字节的数据 */
void copy_from_fifo(uint8_t *buf, fifo_t* fifo, uint8_t len)
{
	uint8_t i = 0;
	while (!(is_empty(fifo)) && i < len) {
		fifo->head = (fifo->head + 1)%(fifo->size);
		buf[i++] = fifo->rxbuffer[fifo->head];
	}
}

/* CAN0 接收中断 */
void USBD_LP_CAN0_RX0_IRQHandler(void)
{
    can_receive_message_struct str_can_rx_msg = {0};

    can_message_receive(CAN0, CAN_FIFO0, &str_can_rx_msg);
    can_rx_iap_cmd(str_can_rx_msg);
    // can_recv_handle(str_can_rx_msg);
}
